package com.senyint.sys.utils.quartz;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.SimpleTrigger;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.triggers.SimpleTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class QuartzJobSimpleUtil extends QuartzJobUtils {

	private static final Logger log = LoggerFactory.getLogger(QuartzJobSimpleUtil.class);

	/**
	 * merge 一个job
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:01:43
	 * @version 1.0
	 * @param scheduler
	 * @param triggerId
	 * @param triggerGroup
	 * @param jobId
	 * @param jobGroup
	 * @param jobClass
	 * @param jobDataMap
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void mergeJob(Scheduler scheduler, String triggerId, String triggerGroup, String jobId, String jobGroup, Class<? extends Job> jobClass, JobDataMap jobDataMap, Date triggerStartTime) throws SchedulerException {
		log.debug("triggerId:{}", triggerId);
		log.debug("triggerGroup:{}", triggerGroup);
		TriggerKey triggerKey = TriggerKey.triggerKey(triggerId, triggerGroup);
		log.debug("triggerKey:{}", triggerKey);
		Trigger trigger = scheduler.getTrigger(triggerKey);
		if (null == trigger) {
			scheduleJob(scheduler, jobId, jobGroup, jobClass, triggerKey, jobDataMap, triggerStartTime);
		} else {
			rescheduleJob(scheduler, (SimpleTrigger) trigger, jobDataMap, triggerStartTime);
		}
	}

	/**
	 * 新增一个job
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:04:30
	 * @version 1.0
	 * @param scheduler
	 * @param jobId
	 * @param jobGroup
	 * @param jobClass
	 * @param triggerId
	 * @param triggerGroup
	 * @param jobDataMap
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void scheduleJob(Scheduler scheduler, String jobId, String jobGroup, Class<? extends Job> jobClass, String triggerId, String triggerGroup, JobDataMap jobDataMap, Date triggerStartTime) throws SchedulerException {
		log.debug("triggerId:{}", triggerId);
		log.debug("triggerGroup:{}", triggerGroup);
		TriggerKey triggerKey = TriggerKey.triggerKey(triggerId, triggerGroup);
		scheduleJob(scheduler, jobId, jobGroup, jobClass, triggerKey, jobDataMap, triggerStartTime);
	}

	/**
	 * 新增一个job
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:01:59
	 * @version 1.0
	 * @param scheduler
	 * @param jobId
	 * @param jobGroup
	 * @param jobClass
	 * @param triggerKey
	 * @param jobDataMap
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void scheduleJob(Scheduler scheduler, String jobId, String jobGroup, Class<? extends Job> jobClass, TriggerKey triggerKey, JobDataMap jobDataMap, Date triggerStartTime) throws SchedulerException {
		log.debug("jobId:{}", jobId);
		log.debug("jobGroup:{}", jobGroup);
		JobKey jobKey = JobKey.jobKey(jobId, jobGroup);
		scheduleJob(scheduler, jobKey, jobClass, triggerKey, jobDataMap, triggerStartTime);
	}

	/**
	 * 新增一个job
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:02:09
	 * @version 1.0
	 * @param scheduler
	 * @param jobKey
	 * @param jobClass
	 * @param triggerKey
	 * @param jobDataMap
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void scheduleJob(Scheduler scheduler, JobKey jobKey, Class<? extends Job> jobClass, TriggerKey triggerKey, JobDataMap jobDataMap, Date triggerStartTime) throws SchedulerException {
		log.debug("jobKey:{}", jobKey);
		log.debug("jobClass:{}", jobClass);
		JobDetail jobDetail = JobBuilder.newJob(jobClass)//
				.withIdentity(jobKey)//
				//.storeDurably(true)// 没有trigger关联时自动删除
				//.requestRecovery()// 失败后重做
				.build();
		jobDetail.getJobDataMap().putAll(jobDataMap);
		scheduleJob(scheduler, jobDetail, triggerKey, triggerStartTime);
	}

	/**
	 * 新增一个job
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:02:23
	 * @version 1.0
	 * @param scheduler
	 * @param jobDetail
	 * @param triggerKey
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void scheduleJob(Scheduler scheduler, JobDetail jobDetail, TriggerKey triggerKey, Date triggerStartTime) throws SchedulerException {
		log.debug("jobDetail:{}", jobDetail);
		log.debug("triggerKey:{}", triggerKey);
		log.debug("triggerStartTime:{}", triggerStartTime);
		if (isValidExpression(triggerStartTime)) {
			SimpleTrigger trigger = TriggerBuilder.newTrigger()//
					.withIdentity(triggerKey)//
					.startAt(triggerStartTime)// 设置开始时间
					.withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(0).withIntervalInSeconds(1))// 执行1次
					.build();
			log.debug("trigger:{}", trigger);
			scheduler.scheduleJob(jobDetail, trigger);
		}
	}

	/**
	 * 更新一个trigger
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午9:02:38
	 * @version 1.0
	 * @param scheduler
	 * @param trigger
	 * @param jobDataMap
	 * @param triggerStartTime
	 * @throws SchedulerException
	 */
	public static void rescheduleJob(Scheduler scheduler, SimpleTrigger trigger, JobDataMap jobDataMap, Date triggerStartTime) throws SchedulerException {
		if (isValidExpression(triggerStartTime)) {
			// Trigger已存在，那么更新相应的定时设置
			TriggerKey triggerKey = trigger.getKey();

			// 按新的triggerStartTime时间重新构建trigger
			trigger = trigger.getTriggerBuilder()//
					.withIdentity(triggerKey)//
					.startAt(triggerStartTime)// 开始时间
					.withSchedule(SimpleScheduleBuilder.simpleSchedule().withRepeatCount(1))// 执行1次
					.build();

			// 重新设置data
			trigger.getJobDataMap().putAll(jobDataMap);

			// 按新的trigger重新设置job执行
			scheduler.rescheduleJob(triggerKey, trigger);
		}
	}

	/**
	 * 验证 时间表达式
	 * <p>
	 * 
	 * @author NaiFei Wang, wangnaifei@senyint.com
	 * @date 2016年3月30日 下午4:38:41
	 * @version 1.0
	 * @param startTime
	 * @return
	 */
	public static boolean isValidExpression(final Date startTime) {
		if (startTime != null) {
			SimpleTriggerImpl trigger = new SimpleTriggerImpl();
			trigger.setStartTime(startTime);
			Date date = trigger.computeFirstFireTime(null);
			return date != null && date.after(new Date());
		} else {
			return false;
		}
	}
}
